import * as vscode from 'vscode';
import * as WebSocket from 'ws';
import * as fs from 'fs';
import * as path from 'path';

// 扩展激活时调用此方法
export function activate(context: vscode.ExtensionContext) {
	console.log('Free WebSocket extension is now active!');

	// 注册打开 WebSocket 面板的命令
	const openPanelDisposable = vscode.commands.registerCommand('free-websocket.openWebSocketPanel', () => {
		WebSocketPanel.createOrShow(context.extensionUri);
	});

	// 注册刷新连接的命令
	const refreshDisposable = vscode.commands.registerCommand('free-websocket.refreshConnection', () => {
		if (WebSocketPanel.currentPanel) {
			WebSocketPanel.currentPanel.refresh();
		}
	});

	// 注册复制消息的命令
	const copyMessageDisposable = vscode.commands.registerCommand('free-websocket.copyMessage', (messageItem: MessageItem) => {
		if (messageItem && messageItem.description) {
			// 将消息内容（描述）复制到剪贴板
			vscode.env.clipboard.writeText(messageItem.description);
			vscode.window.showInformationMessage('消息内容已复制到剪贴板');
		}
	});

	// 注册侧边栏视图的树数据提供器
	const connectionProvider = new WebSocketConnectionProvider();
	const messagesProvider = new WebSocketMessagesProvider();

	vscode.window.registerTreeDataProvider('free-websocket-connection', connectionProvider);
	vscode.window.registerTreeDataProvider('free-websocket-messages', messagesProvider);

	// 全局存储提供器以便从 WebSocketPanel 访问
	WebSocketPanel.connectionProvider = connectionProvider;
	WebSocketPanel.messagesProvider = messagesProvider;

	context.subscriptions.push(openPanelDisposable, refreshDisposable, copyMessageDisposable);
}

// 扩展停用时调用此方法
export function deactivate() {}

/**
 * 管理 WebSocket 面板
 */
class WebSocketPanel {
	public static currentPanel: WebSocketPanel | undefined;
	public static connectionProvider: WebSocketConnectionProvider;
	public static messagesProvider: WebSocketMessagesProvider;

	private static readonly viewType = 'freeWebSocketPanel';

	private readonly _panel: vscode.WebviewPanel;
	private readonly _extensionUri: vscode.Uri;
	private readonly _disposables: vscode.Disposable[] = [];
	private _webSocket: WebSocket.WebSocket | undefined;
	private _isConnected = false;
	private _lastSentMessageType = 'text'; // 跟踪最后发送的消息类型

	public static createOrShow(extensionUri: vscode.Uri) {
		const column = vscode.window.activeTextEditor
			? vscode.window.activeTextEditor.viewColumn
			: undefined;

		// 如果已经有面板，则显示它
		if (WebSocketPanel.currentPanel) {
			WebSocketPanel.currentPanel._panel.reveal(column);
			return;
		}

		// 否则，创建一个新面板
		const panel = vscode.window.createWebviewPanel(
			WebSocketPanel.viewType,
			'Free WebSocket',
			column || vscode.ViewColumn.One,
			{
				enableScripts: true,
				localResourceRoots: [
					vscode.Uri.joinPath(extensionUri, 'media'),
					vscode.Uri.joinPath(extensionUri, 'out', 'compiled')
				]
			}
		);

		WebSocketPanel.currentPanel = new WebSocketPanel(panel, extensionUri);
	}

	public static kill() {
		WebSocketPanel.currentPanel?.dispose();
		WebSocketPanel.currentPanel = undefined;
	}

	public static revive(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
		WebSocketPanel.currentPanel = new WebSocketPanel(panel, extensionUri);
	}

	private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
		this._panel = panel;
		this._extensionUri = extensionUri;

		// 设置 webview 的初始 HTML 内容
		this._update();

		// 监听面板被销毁的事件
		// 当用户关闭面板或以编程方式关闭面板时会发生这种情况
		this._panel.onDidDispose(() => this.dispose(), null, this._disposables);

		// 处理来自 webview 的消息
		this._panel.webview.onDidReceiveMessage(
			(message) => {
				switch (message.command) {
					case 'connect':
						this._connect(message.url, message.certificatePath);
						return;
					case 'disconnect':
						this._disconnect();
						return;
					case 'send':
						this._sendMessage(message.text, message.originalText, message.type);
						return;
					case 'selectCertificate':
						this._selectCertificate();
						return;
				}
			},
			null,
			this._disposables
		);
	}

	public refresh() {
		this._update();
	}

	public dispose() {
		WebSocketPanel.currentPanel = undefined;

		// 清理我们的资源
		this._panel.dispose();
		this._disconnect();

		while (this._disposables.length) {
			const x = this._disposables.pop();
			if (x) {
				x.dispose();
			}
		}
	}

	private _update() {
		const webview = this._panel.webview;
		this._panel.webview.html = this._getHtmlForWebview(webview);
	}

	private _connect(url: string, certificatePath?: string) {
		if (this._isConnected && this._webSocket) {
			this._disconnect();
		}

		try {
			const options: any = {};
			
			// 如果提供了证书路径，设置 SSL 选项
			if (certificatePath && certificatePath.trim() !== '') {
				try {
					if (fs.existsSync(certificatePath)) {
						// 检查文件扩展名
						const validExtensions = ['.pem', '.crt', '.cer', '.cert'];
						const ext = path.extname(certificatePath).toLowerCase();
						
						if (!validExtensions.includes(ext)) {
							this._panel.webview.postMessage({
								command: 'error',
								message: `Invalid certificate file format. Supported formats: ${validExtensions.join(', ')}`
							});
							return;
						}
						
						// 读取证书文件
						const certData = fs.readFileSync(certificatePath);
						
						// 验证证书格式（基本检查）
						const certString = certData.toString();
						if (!certString.includes('-----BEGIN CERTIFICATE-----') && 
							!certString.includes('-----BEGIN TRUSTED CERTIFICATE-----')) {
							this._panel.webview.postMessage({
								command: 'error',
								message: 'Invalid certificate format. File does not appear to be a valid certificate.'
							});
							return;
						}
						
						options.ca = [certData];
						options.rejectUnauthorized = false; // For self-signed certificates
						
						// 通知用户证书已加载
						this._panel.webview.postMessage({
							command: 'info',
							message: `Using certificate: ${path.basename(certificatePath)}`
						});
					} else {
						this._panel.webview.postMessage({
							command: 'error',
							message: `Certificate file not found: ${certificatePath}`
						});
						return;
					}
				} catch (error) {
					this._panel.webview.postMessage({
						command: 'error',
						message: `Failed to read certificate: ${error instanceof Error ? error.message : error}`
					});
					return;
				}
			}

			this._webSocket = new WebSocket.WebSocket(url, options);

			this._webSocket.on('open', () => {
				this._isConnected = true;
				this._panel.webview.postMessage({
					command: 'connected',
					message: `Connected to ${url}`,
					url: url
				});
				
				// 更新侧边栏连接状态
				if (WebSocketPanel.connectionProvider) {
					WebSocketPanel.connectionProvider.updateConnection('Connected', url);
				}
				if (WebSocketPanel.messagesProvider) {
					WebSocketPanel.messagesProvider.addMessage('Connected', `Connected to ${url}`);
				}
			});

		this._webSocket.on('message', (data) => {
			let messageText = '';
			if (Buffer.isBuffer(data)) {
				messageText = data.toString('utf8');
			} else if (data instanceof ArrayBuffer) {
				messageText = new TextDecoder().decode(data);
			} else {
				messageText = data.toString();
			}
			
			this._panel.webview.postMessage({
				command: 'message',
				message: messageText,
				suggestedResponseType: this._lastSentMessageType // 发送最后发送的消息类型作为建议
			});
			
			// 更新侧边栏消息
			if (WebSocketPanel.messagesProvider) {
				WebSocketPanel.messagesProvider.addMessage('Received', messageText);
			}
		});			this._webSocket.on('close', () => {
				this._isConnected = false;
				this._panel.webview.postMessage({
					command: 'disconnected',
					message: 'Connection closed'
				});
				
				// 更新侧边栏连接状态
				if (WebSocketPanel.connectionProvider) {
					WebSocketPanel.connectionProvider.updateConnection('Disconnected', '');
				}
				if (WebSocketPanel.messagesProvider) {
					WebSocketPanel.messagesProvider.addMessage('Disconnected', 'Connection closed');
				}
			});

			this._webSocket.on('error', (error) => {
				console.error('WebSocket error:', error);
				
				// 分析错误类型，提供更友好的提示
				let friendlyMessage = '';
				const errorMsg = error.message.toLowerCase();
				
				if (errorMsg.includes('eproto') && errorMsg.includes('wrong_version_number')) {
					// SSL/TLS 协议错误 - 通常是 wss:// 连接到非安全端口
					friendlyMessage = 'SSL/TLS Error: Trying to connect securely (wss://) to a non-secure server. Try using ws:// instead, or use a different port that supports SSL.';
				} else if (errorMsg.includes('econnrefused')) {
					friendlyMessage = 'Connection refused: Server is not running or port is blocked.';
				} else if (errorMsg.includes('getaddrinfo') || errorMsg.includes('enotfound')) {
					friendlyMessage = 'Host not found: Check the server address.';
				} else if (errorMsg.includes('certificate')) {
					friendlyMessage = 'Certificate error: Invalid or untrusted certificate. Try providing a valid certificate file.';
				} else {
					friendlyMessage = `Connection error: ${error.message}`;
				}
				
				this._panel.webview.postMessage({
					command: 'error',
					message: friendlyMessage
				});
				
				// 更新侧边栏消息
				if (WebSocketPanel.messagesProvider) {
					WebSocketPanel.messagesProvider.addMessage('Error', friendlyMessage);
				}
			});

		} catch (error) {
			this._panel.webview.postMessage({
				command: 'error',
				message: `Failed to connect: ${error}`
			});
		}
	}

	private _disconnect() {
		if (this._webSocket) {
			this._webSocket.close();
			this._webSocket = undefined;
		}
		this._isConnected = false;
		
		// 更新侧边栏连接状态
		if (WebSocketPanel.connectionProvider) {
			WebSocketPanel.connectionProvider.updateConnection('Disconnected', '');
		}
	}

	private _sendMessage(message: string, originalText?: string, messageType?: string) {
		if (this._webSocket && this._isConnected) {
			// 记住最后发送的消息类型
			this._lastSentMessageType = messageType || 'text';
			
			this._webSocket.send(message);
			
			this._panel.webview.postMessage({
				command: 'sent',
				message: `Sent: ${originalText || message}`,
				originalText: originalText || message,
				type: messageType || 'text'
			});
			
			// 更新侧边栏消息
			if (WebSocketPanel.messagesProvider) {
				WebSocketPanel.messagesProvider.addMessage('Sent', originalText || message);
			}
		} else {
			this._panel.webview.postMessage({
				command: 'error',
				message: 'Not connected to WebSocket'
			});
			
			// 更新侧边栏消息
			if (WebSocketPanel.messagesProvider) {
				WebSocketPanel.messagesProvider.addMessage('Error', 'Not connected to WebSocket');
			}
		}
	}

	private async _selectCertificate() {
		const options: vscode.OpenDialogOptions = {
			canSelectMany: false,
			openLabel: 'Select Certificate',
			filters: {
				'Certificate files': ['crt', 'cer', 'pem', 'cert'],
				'All files': ['*']
			}
		};

		const fileUri = await vscode.window.showOpenDialog(options);
		if (fileUri && fileUri[0]) {
			this._panel.webview.postMessage({
				command: 'certificateSelected',
				path: fileUri[0].fsPath
			});
		}
	}

	private _getHtmlForWebview(webview: vscode.Webview) {
		return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Free WebSocket</title>
    <style>
        body {
            font-family: var(--vscode-font-family);
            padding: 20px;
            color: var(--vscode-foreground);
            background-color: var(--vscode-editor-background);
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
        }
        .section {
            margin-bottom: 20px;
            padding: 15px;
            border: 1px solid var(--vscode-panel-border);
            border-radius: 5px;
            background-color: var(--vscode-panel-background);
        }
        .section h3 {
            margin-top: 0;
            color: var(--vscode-foreground);
        }
        .input-group {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
            align-items: center;
        }
        .input-group label {
            min-width: 80px;
            font-weight: bold;
        }
        input[type="text"], input[type="url"] {
            flex: 1;
            padding: 8px;
            border: 1px solid var(--vscode-input-border);
            background-color: var(--vscode-input-background);
            color: var(--vscode-input-foreground);
            border-radius: 3px;
        }
        input[type="text"]:focus, input[type="url"]:focus {
            outline: 1px solid var(--vscode-focusBorder);
        }
        button {
            padding: 8px 16px;
            border: none;
            border-radius: 3px;
            background-color: var(--vscode-button-background);
            color: var(--vscode-button-foreground);
            cursor: pointer;
            font-size: 14px;
        }
        button:hover {
            background-color: var(--vscode-button-hoverBackground);
        }
        button:disabled {
            background-color: var(--vscode-button-secondaryBackground);
            color: var(--vscode-button-secondaryForeground);
            cursor: not-allowed;
        }
        .connect-btn {
            min-width: 80px;
        }
        .connect-btn.connected {
            background-color: var(--vscode-errorForeground);
        }
        textarea {
            width: 100%;
            min-height: 100px;
            padding: 8px;
            border: 1px solid var(--vscode-input-border);
            background-color: var(--vscode-input-background);
            color: var(--vscode-input-foreground);
            border-radius: 3px;
            resize: vertical;
            font-family: var(--vscode-editor-font-family);
        }
        textarea:focus {
            outline: 1px solid var(--vscode-focusBorder);
        }
        .message-area {
            background-color: var(--vscode-editor-background);
            border: 1px solid var(--vscode-input-border);
            padding: 10px;
            min-height: 200px;
            max-height: 400px;
            overflow-y: auto;
            font-family: var(--vscode-editor-font-family);
            font-size: var(--vscode-editor-font-size);
            border-radius: 3px;
            white-space: pre-wrap;
        }
        .status {
            padding: 8px 12px;
            margin: 8px 0;
            border-radius: 3px;
            font-weight: bold;
            text-align: center;
            min-height: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            opacity: 0;
            transition: opacity 0.3s ease;
            border: 1px solid transparent;
        }
        .status.visible {
            opacity: 1;
        }
        .status.connected {
            background-color: var(--vscode-terminal-ansiGreen);
            color: var(--vscode-terminal-background);
            border-color: var(--vscode-terminal-ansiGreen);
        }
        .status.disconnected {
            background-color: var(--vscode-terminal-ansiRed);
            color: var(--vscode-terminal-background);
            border-color: var(--vscode-terminal-ansiRed);
        }
        .status.error {
            background-color: var(--vscode-errorForeground);
            color: var(--vscode-errorBackground);
            border-color: var(--vscode-errorForeground);
        }
        .status.info {
            background-color: var(--vscode-notificationsInfoIcon-foreground);
            color: var(--vscode-editor-background);
            border-color: var(--vscode-notificationsInfoIcon-foreground);
        }
        
        /* 连接状态指示器 */
        .connection-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .connection-status {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 12px;
            color: var(--vscode-descriptionForeground);
        }
        .status-indicator {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background-color: var(--vscode-terminal-ansiRed);
        }
        .status-indicator.connected {
            background-color: var(--vscode-terminal-ansiGreen);
        }
        .status-indicator.connecting {
            background-color: var(--vscode-terminal-ansiYellow);
            animation: pulse 1s infinite;
        }
        @keyframes pulse {
            0% { opacity: 1; }
            50% { opacity: 0.3; }
            100% { opacity: 1; }
        }
        .cert-info {
            margin-top: 5px;
            padding: 8px;
            background-color: var(--vscode-editor-background);
            border-left: 3px solid var(--vscode-notificationsInfoIcon-foreground);
            border-radius: 3px;
        }
        .tab-container {
            display: flex;
            gap: 5px;
            flex-wrap: wrap;
        }
        .tab-btn, .response-tab-btn {
            padding: 4px 8px;
            border: 1px solid var(--vscode-input-border);
            border-radius: 3px;
            background-color: var(--vscode-button-secondaryBackground);
            color: var(--vscode-button-secondaryForeground);
            cursor: pointer;
            font-size: 12px;
            min-width: 50px;
        }
        .tab-btn.active, .response-tab-btn.active {
            background-color: var(--vscode-button-background);
            color: var(--vscode-button-foreground);
        }
        .tab-btn:hover, .response-tab-btn:hover {
            background-color: var(--vscode-button-hoverBackground);
        }
        .format-error {
            color: var(--vscode-errorForeground);
            font-style: italic;
            margin-top: 5px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Free WebSocket Client</h1>
        
        <!-- Connection Section -->
        <div class="section">
            <div class="connection-header">
                <h3>Connection</h3>
                <div class="connection-status">
                    <div id="statusIndicator" class="status-indicator"></div>
                    <span id="statusText">Disconnected</span>
                </div>
            </div>
            <div class="input-group">
                <label for="url">URL:</label>
                <input type="url" id="url" placeholder="ws://localhost:8080 (non-secure) or wss://localhost:8443 (secure)" value="ws://localhost:8080">
                <button id="connectBtn" class="connect-btn">Connect</button>
            </div>
            <div class="input-group">
                <label for="cert">Certificate:</label>
                <input type="text" id="cert" placeholder="Only needed for self-signed certificates (optional)">
                <button id="selectCertBtn">Browse</button>
            </div>
            <div class="cert-info">
                <small style="color: var(--vscode-descriptionForeground); font-style: italic;">
                    ℹ️ Most wss:// connections work without certificates. Only provide a certificate for self-signed or private CA servers.
                </small>
            </div>
            <div id="status" class="status"></div>
        </div>

        <!-- Send Message Section -->
        <div class="section">
            <h3>Send Message</h3>
            <div class="input-group">
                <label for="messageType">Type:</label>
                <div class="tab-container">
                    <button class="tab-btn active" data-type="text">Text</button>
                    <button class="tab-btn" data-type="json">JSON</button>
                </div>
            </div>
            <div class="input-group">
                <textarea id="messageInput" placeholder="Enter your message here..."></textarea>
            </div>
            <div class="input-group">
                <button id="sendBtn" disabled>Send</button>
            </div>
        </div>

        <!-- Response Section -->
        <div class="section">
            <h3>Latest Response</h3>
            <div class="input-group">
                <label for="responseType">View as:</label>
                <div class="tab-container">
                    <button class="response-tab-btn active" data-type="text">Text</button>
                    <button class="response-tab-btn" data-type="json">JSON</button>
                </div>
            </div>
            <div id="messages" class="message-area"></div>
            <div class="input-group" style="margin-top: 10px;">
                <button id="clearBtn">Clear Display</button>
            </div>
        </div>
    </div>

    <script>
        const vscode = acquireVsCodeApi();
        
        let isConnected = false;
        let currentMessageType = 'text';
        let currentResponseType = 'text';
        let messageHistory = [];
        
        const connectBtn = document.getElementById('connectBtn');
        const sendBtn = document.getElementById('sendBtn');
        const clearBtn = document.getElementById('clearBtn');
        const selectCertBtn = document.getElementById('selectCertBtn');
        const urlInput = document.getElementById('url');
        const certInput = document.getElementById('cert');
        const messageInput = document.getElementById('messageInput');
        const messagesDiv = document.getElementById('messages');
        const statusDiv = document.getElementById('status');
        const statusIndicator = document.getElementById('statusIndicator');
        const statusText = document.getElementById('statusText');

        // Tab handling
        const tabBtns = document.querySelectorAll('.tab-btn');
        const responseTabBtns = document.querySelectorAll('.response-tab-btn');

        tabBtns.forEach(btn => {
            btn.addEventListener('click', () => {
                // 记录之前的格式
                window.previousMessageType = currentMessageType;
                
                tabBtns.forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                currentMessageType = btn.dataset.type;
                
                // 自动格式化当前输入的内容
                formatMessageInput();
            });
        });

        responseTabBtns.forEach(btn => {
            btn.addEventListener('click', () => {
                responseTabBtns.forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                currentResponseType = btn.dataset.type;
                refreshMessages();
            });
        });

        function setResponseType(type) {
            if (type === 'text' || type === 'json') {
                currentResponseType = type;
                responseTabBtns.forEach(btn => {
                    btn.classList.remove('active');
                    if (btn.dataset.type === type) {
                        btn.classList.add('active');
                    }
                });
                refreshMessages();
            }
        }

        // 事件监听器
        connectBtn.addEventListener('click', () => {
            if (isConnected) {
                disconnect();
            } else {
                connect();
            }
        });

        sendBtn.addEventListener('click', () => {
            sendMessage();
        });

        clearBtn.addEventListener('click', () => {
            // 只清空主面板显示，保留侧边栏历史记录
            messagesDiv.textContent = '';
            // 注意：不清空 messageHistory，让侧边栏保持完整历史
        });

        selectCertBtn.addEventListener('click', () => {
            vscode.postMessage({
                command: 'selectCertificate'
            });
        });

        messageInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && e.ctrlKey) {
                sendMessage();
            }
        });

        function connect() {
            const url = urlInput.value.trim();
            if (!url) {
                showStatus('Please enter a WebSocket URL', 'error');
                return;
            }

            // URL 验证和提示
            if (!url.startsWith('ws://') && !url.startsWith('wss://')) {
                showStatus('URL must start with ws:// or wss://', 'error');
                return;
            }

            // 检查是否使用了错误的协议组合
            const isSecureProtocol = url.startsWith('wss://');
            const hasCertificate = certInput.value.trim() !== '';
            
            if (isSecureProtocol && !hasCertificate) {
                const port = url.split(':').pop();
                if (port === '8080') {
                    showStatus('Tip: Port 8080 usually runs non-secure WebSocket. Try ws:// instead of wss://', 'info');
                    // 不要 return，让用户尝试连接
                } else {
                    // 对于其他端口，只是提示，不阻止连接
                    showStatus('Connecting to wss:// without certificate (works for most public servers)', 'info');
                }
            }

            // 显示连接中状态
            updateConnectionStatus('connecting');

            vscode.postMessage({
                command: 'connect',
                url: url,
                certificatePath: certInput.value.trim()
            });
        }

        function disconnect() {
            vscode.postMessage({
                command: 'disconnect'
            });
        }

        function sendMessage() {
            const message = messageInput.value.trim();
            if (!message) {
                showStatus('Please enter a message to send', 'error');
                return;
            }
            
            vscode.postMessage({
                command: 'send',
                text: message,
                originalText: message,
                type: currentMessageType
            });
        }

        function formatMessageInput() {
            const message = messageInput.value.trim();
            if (!message) {
                return;
            }

            try {
                const previousFormat = window.previousMessageType || 'text';
                
                if (currentMessageType === 'json' && previousFormat === 'text') {
                    try {
                        const parsed = JSON.parse(message);
                        messageInput.value = JSON.stringify(parsed, null, 2);
                    } catch (e) {
                        messageInput.value = message;
                    }
                } else if (currentMessageType === 'text' && previousFormat === 'json') {
                    try {
                        const parsed = JSON.parse(message);
                        messageInput.value = JSON.stringify(parsed);
                    } catch (e) {
                        messageInput.value = message;
                    }
                }
            } catch (error) {
                console.log('Format warning:', error.message);
            }
        }

        function formatDisplayText(text, type) {
            try {
                if (type === 'json') {
                    // 首先尝试解析为 JSON
                    const parsed = JSON.parse(text);
                    return JSON.stringify(parsed, null, 2);
                }
                return text;
            } catch (error) {
                if (type === 'json') {
                    // 如果 JSON 解析失败，尝试从文本中提取 JSON
                    const jsonMatch = text.match(/\\{.*\\}|\\[.*\\]/s);
                    if (jsonMatch) {
                        try {
                            const parsed = JSON.parse(jsonMatch[0]);
                            const prefix = text.substring(0, jsonMatch.index);
                            const suffix = text.substring(jsonMatch.index + jsonMatch[0].length);
                            const formattedJson = JSON.stringify(parsed, null, 2);
                            return prefix + formattedJson + suffix;
                        } catch (innerError) {
                            // 如果提取也失败，返回带错误提示的文本
                            return '[Note: Contains non-JSON content, displaying as text]\\n' + text;
                        }
                    } else {
                        // 未找到 JSON，显示为文本
                        return '[Note: No JSON content found, displaying as text]\\n' + text;
                    }
                }
                return text;
            }
        }

        function showStatus(message, type) {
            // 更新状态区域（仅用于临时消息）
            if (type === 'error' || type === 'info') {
                statusDiv.textContent = message;
                statusDiv.className = 'status ' + type + ' visible';
                
                setTimeout(() => {
                    statusDiv.classList.remove('visible');
                }, 5000);
            }
        }
        
        function updateConnectionStatus(status, url = '') {
            // 更新连接状态指示器
            statusIndicator.className = 'status-indicator ' + status;
            
            switch(status) {
                case 'connected':
                    statusText.textContent = 'Connected to ' + url;
                    connectBtn.textContent = 'Disconnect';
                    connectBtn.disabled = false;
                    sendBtn.disabled = false;
                    break;
                case 'connecting':
                    statusText.textContent = 'Connecting...';
                    connectBtn.textContent = 'Connecting...';
                    connectBtn.disabled = true;
                    sendBtn.disabled = true;
                    break;
                case 'disconnected':
                default:
                    statusText.textContent = 'Disconnected';
                    connectBtn.textContent = 'Connect';
                    connectBtn.disabled = false;
                    sendBtn.disabled = true;
                    break;
                    break;
            }
        }

        function addMessage(message, type = '', originalText = '') {
            const timestamp = new Date().toLocaleTimeString();
            const messageObj = {
                timestamp,
                message,
                type,
                originalText: originalText || message
            };
            
            // 添加到历史记录（用于侧边栏）
            messageHistory.push(messageObj);
            
            // 根据消息类型决定主面板显示逻辑
            if (type === 'received') {
                // 收到消息时，主面板只显示最新的接收消息
                showLatestReceivedMessage(messageObj);
            } else if (type === 'sent') {
                // 发送消息时，在主面板显示发送的消息
                appendToMainPanel(messageObj);
            } else {
                // 连接状态等其他消息，正常添加到主面板
                appendToMainPanel(messageObj);
            }
        }

        function showLatestReceivedMessage(messageObj) {
            // 清空主面板，只显示最新收到的消息
            messagesDiv.textContent = '';
            const displayText = formatDisplayText(messageObj.originalText, currentResponseType);
            const formattedMessage = \`[\${messageObj.timestamp}] Latest Response:\\n\${displayText}\`;
            messagesDiv.textContent = formattedMessage;
            messagesDiv.scrollTop = messagesDiv.scrollHeight;
        }

        function appendToMainPanel(messageObj) {
            // 将消息添加到主面板（不清空现有内容）
            const displayText = formatDisplayText(messageObj.originalText, currentResponseType);
            const formattedMessage = \`[\${messageObj.timestamp}] \${messageObj.message.split(':')[0]}: \${displayText}\`;
            messagesDiv.textContent += formattedMessage + '\\n';
            messagesDiv.scrollTop = messagesDiv.scrollHeight;
        }

        function refreshMessages() {
            // 保持现有的刷新逻辑（可能用于格式切换）
            messagesDiv.textContent = '';
            
            // 只显示最新的接收消息（如果有的话）
            const latestReceived = messageHistory.slice().reverse().find(msg => msg.type === 'received');
            if (latestReceived) {
                showLatestReceivedMessage(latestReceived);
            } else {
                // 如果没有接收消息，显示所有消息
                messageHistory.forEach(msg => {
                    appendToMainPanel(msg);
                });
            }
        }

        function setConnectedState(connected, url = '') {
            isConnected = connected;
            urlInput.disabled = connected;
            certInput.disabled = connected;
            selectCertBtn.disabled = connected;
            
            if (connected) {
                updateConnectionStatus('connected', url);
            } else {
                updateConnectionStatus('disconnected');
            }
        }

        // 处理来自扩展的消息
        window.addEventListener('message', event => {
            const message = event.data;
            
            switch (message.command) {
                case 'connected':
                    setConnectedState(true, message.url || urlInput.value);
                    addMessage('Connected: ' + message.message);
                    break;
                    
                case 'disconnected':
                    setConnectedState(false);
                    addMessage('Disconnected: ' + message.message);
                    break;
                    
                case 'message':
                    // 自动设置响应类型以匹配最后发送的消息类型
                    if (message.suggestedResponseType) {
                        setResponseType(message.suggestedResponseType);
                    }
                    addMessage('Received: ' + message.message, 'received', message.message);
                    break;
                    
                case 'sent':
                    addMessage(message.message, 'sent', message.originalText || message.message.replace('Sent: ', ''));
                    // 不清除输入框内容
                    break;
                    
                case 'error':
                    setConnectedState(false);
                    showStatus(message.message, 'error');
                    addMessage('Error: ' + message.message);
                    break;
                    
                case 'info':
                    showStatus(message.message, 'info');
                    break;
                    
                case 'certificateSelected':
                    certInput.value = message.path;
                    break;
            }
        });
    </script>
</body>
</html>`;
	}
}

/**
 * WebSocket 连接视图的树数据提供器
 */
class WebSocketConnectionProvider implements vscode.TreeDataProvider<ConnectionItem> {
	private _onDidChangeTreeData: vscode.EventEmitter<ConnectionItem | undefined | null | void> = new vscode.EventEmitter<ConnectionItem | undefined | null | void>();
	readonly onDidChangeTreeData: vscode.Event<ConnectionItem | undefined | null | void> = this._onDidChangeTreeData.event;

	private connectionStatus: string = 'Disconnected';
	private connectionUrl: string = '';

	constructor() {}

	refresh(): void {
		this._onDidChangeTreeData.fire();
	}

	getTreeItem(element: ConnectionItem): vscode.TreeItem {
		return element;
	}

	getChildren(element?: ConnectionItem): Thenable<ConnectionItem[]> {
		if (!element) {
			return Promise.resolve([
				new ConnectionItem('Status', this.connectionStatus, vscode.TreeItemCollapsibleState.None),
				new ConnectionItem('URL', this.connectionUrl || 'Not connected', vscode.TreeItemCollapsibleState.None),
				new ConnectionItem('Actions', '', vscode.TreeItemCollapsibleState.Expanded)
			]);
		} else if (element.label === 'Actions') {
			return Promise.resolve([
				new ConnectionItem('Open Panel', 'Click to open WebSocket panel', vscode.TreeItemCollapsibleState.None, {
					command: 'free-websocket.openWebSocketPanel',
					title: 'Open WebSocket Panel'
				})
			]);
		}
		return Promise.resolve([]);
	}

	updateConnection(status: string, url: string) {
		this.connectionStatus = status;
		this.connectionUrl = url;
		this.refresh();
	}
}

/**
 * WebSocket 消息视图的树数据提供器
 */
class WebSocketMessagesProvider implements vscode.TreeDataProvider<MessageItem> {
	private _onDidChangeTreeData: vscode.EventEmitter<MessageItem | undefined | null | void> = new vscode.EventEmitter<MessageItem | undefined | null | void>();
	readonly onDidChangeTreeData: vscode.Event<MessageItem | undefined | null | void> = this._onDidChangeTreeData.event;

	private messages: MessageItem[] = [];

	constructor() {}

	refresh(): void {
		this._onDidChangeTreeData.fire();
	}

	getTreeItem(element: MessageItem): vscode.TreeItem {
		return element;
	}

	getChildren(element?: MessageItem): Thenable<MessageItem[]> {
		return Promise.resolve(this.messages);
	}

	addMessage(type: string, content: string) {
		const timestamp = new Date().toLocaleTimeString();
		this.messages.push(new MessageItem(`[${timestamp}] ${type}`, content, vscode.TreeItemCollapsibleState.None));
		// 只保留最近20条消息
		if (this.messages.length > 20) {
			this.messages = this.messages.slice(-20);
		}
		this.refresh();
	}

	clearMessages() {
		this.messages = [];
		this.refresh();
	}
}

/**
 * 树视图的连接项
 */
class ConnectionItem extends vscode.TreeItem {
	constructor(
		public readonly label: string,
		public readonly description: string,
		public readonly collapsibleState: vscode.TreeItemCollapsibleState,
		public readonly command?: vscode.Command
	) {
		super(label, collapsibleState);
		this.tooltip = description;
		this.description = description;
		
		if (label === 'Status') {
			this.iconPath = description === 'Connected' ? 
				new vscode.ThemeIcon('check', new vscode.ThemeColor('terminal.ansiGreen')) :
				new vscode.ThemeIcon('close', new vscode.ThemeColor('terminal.ansiRed'));
		} else if (label === 'URL') {
			this.iconPath = new vscode.ThemeIcon('globe');
		} else if (label === 'Actions') {
			this.iconPath = new vscode.ThemeIcon('tools');
		} else if (label === 'Open Panel') {
			this.iconPath = new vscode.ThemeIcon('window');
		}
	}
}

/**
 * 树视图的消息项
 */
class MessageItem extends vscode.TreeItem {
	constructor(
		public readonly label: string,
		public readonly description: string,
		public readonly collapsibleState: vscode.TreeItemCollapsibleState
	) {
		super(label, collapsibleState);
		this.tooltip = `${description}\n\n点击复制消息内容`;
		
		// 为每个消息项添加复制命令
		this.command = {
			command: 'free-websocket.copyMessage',
			title: '复制消息',
			arguments: [this]
		};
		
		if (label.includes('Sent:')) {
			this.iconPath = new vscode.ThemeIcon('arrow-up', new vscode.ThemeColor('terminal.ansiBlue'));
		} else if (label.includes('Received:')) {
			this.iconPath = new vscode.ThemeIcon('arrow-down', new vscode.ThemeColor('terminal.ansiGreen'));
		} else if (label.includes('Connected:')) {
			this.iconPath = new vscode.ThemeIcon('plug', new vscode.ThemeColor('terminal.ansiGreen'));
		} else if (label.includes('Disconnected:')) {
			this.iconPath = new vscode.ThemeIcon('debug-disconnect', new vscode.ThemeColor('terminal.ansiRed'));
		} else {
			this.iconPath = new vscode.ThemeIcon('info');
		}
	}
}
